/**
 /**
 * The graphicalChess class for the Graphical Chess game.
 * 
 * @author Jan Mikhail
 */


package mainClasses;
import pieces.*;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.soap.Node;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

public class GraphicalChess extends JPanel implements BoardGame, ActionListener{
	/**
	 * Size of the board
	 */
	private static final int SIZE = 8;										
	
	/**
	 * The board used for the current game
	 */
	private Board board1;													
	
	/**
	 * Panel used to organize the inner game panel
	 */
	JPanel boardLayout;	
	
	/**
	 * A 2D array of pieces
	 */
	Piece[][] items;
	
	/**
	 * A 2D array of buttons that correspond to the board blocks
	 */
	JButton[][] buttons;	

	/**
	 * A boolean that holds the current turn
	 */
	boolean player1 = true;

	/**
	 * A boolean that states whethe a piece is selected or not
	 */
	boolean selected = false;

	
	boolean kingIsInDanger = false;
	
	/**
	 * A temporary null piece that is used to hold the king after a check to check
	 * if the check still exists
	 */
	Piece afterKingInDanger = new NullPiece(100, 100, board1);		
	
	/**
	 * A temporary null piece that is used to hold the king after a check to check
	 * if the check still exists
	 */
	Piece afterKingInDanger2 = new NullPiece(100, 100, board1);
	
	/**
	 * The input and output fields that are used to communicate with the player
	 */
	InputAndOutput io;
	
	/**
	 * Boolean to specify if the game has ended
	 */
	boolean lostOrWon = false;
	
	/**
	 * The coordinates of the current selected piece
	 */
	Point selection =  new Point(10, 10);

	/**
	 * Player 1's name
	 */
	public String playerOneName = "Player 1";
	
	/**
	 * Player 2's name
	 */
	public String playerTwoName = "Player 2";
	
	/**
	 * Boolean to state whether player 1 has been named
	 */
	boolean playerOneNamed = false;

	/**
	 * Boolean to state whether player 2 has been named
	 */
	boolean playerTwoNamed = true;
	
	boolean pawnTransformation = false;
	Piece pawn = new NullPiece(0, 0, this.board1);
	public boolean kingCheckMove = false;
	
	boolean stopGame = false;
	
	
	/*
	 * The following instance variables are used for redo and undo
	 */
	public int moveNumber = 0;
	ArrayList<Board> boards = new ArrayList<Board>();
	ArrayList<Boolean> players = new ArrayList<Boolean>();
	ArrayList<Boolean> kingindangers = new ArrayList<Boolean>();
	ArrayList<InputAndOutput> ios = new ArrayList<InputAndOutput>();
	ArrayList<Boolean> lostOrWons = new ArrayList<Boolean>();
	ArrayList<Boolean> pawnTransformations = new ArrayList<Boolean>();
	ArrayList<Piece> pawns = new ArrayList<Piece>();
	
	public int moveNumberRedo = 0;
	ArrayList<Board> boardsredo = new ArrayList<Board>();
	ArrayList<Boolean> playersredo = new ArrayList<Boolean>();
	ArrayList<Boolean> kingindangersredo = new ArrayList<Boolean>();
	ArrayList<InputAndOutput> iosredo = new ArrayList<InputAndOutput>();
	ArrayList<Boolean> lostOrWonsredo = new ArrayList<Boolean>();
	ArrayList<Boolean> pawnTransformationsredo = new ArrayList<Boolean>();
	ArrayList<Piece> pawnsredo = new ArrayList<Piece>();
	
	JButton restart = new JButton("Restart");
	JButton exit = new JButton("Exit");
	JButton promptButtons[];
	
	JButton queenButton = new JButton("Queen");
	JButton rookButton = new JButton("Rook");
	JButton bishopButton = new JButton("Bishop");
	JButton knightButton = new JButton("Knight");
	JButton pieceButtons[];
	
	/**
	 * Specifies if the save and load options are allowed at the current time
	 */
	public boolean safeToSaveLoad = false;
	
	
	
	Piece select = new NullPiece(10,10, this.board1);
	Piece selectDest = new NullPiece(10,10, this.board1);
	boolean selectionDone = false;
	Color color;
	
	HelpAndAbout frame;
	
	
	
	
	/**
	 * Constructor for the Game class. It creates an instance of a board
	 */
	public GraphicalChess(InputAndOutput io)													//Constructor for game
	{
		this.promptButtons = new JButton[2];
		this.promptButtons[0] = this.restart;
		this.promptButtons[1] = this.exit;
		this.restart.addActionListener(this);
		this.exit.addActionListener(this);
		
		/*
		 * The buttons that are used to get the user's choice of pieces when
		 * a pawn is promoted
		 */
		this.pieceButtons = new JButton[4];
		this.pieceButtons[0] = this.queenButton;
		this.pieceButtons[1] = this.rookButton;
		this.pieceButtons[2] = this.bishopButton;
		this.pieceButtons[3] = this.knightButton;
		
		this.queenButton.addActionListener(this);
		this.rookButton.addActionListener(this);
		this.bishopButton.addActionListener(this);
		this.knightButton.addActionListener(this);
		
		
		buttons = new JButton[SIZE][SIZE];	//2D array of buttons
		this.setLayout(new BorderLayout());
		this.boardLayout  = new JPanel();
		this.boardLayout.setLayout(new GridLayout(SIZE, SIZE));
		for (int i = SIZE-1; i >= 0; i--) 
		{
			for (int j = 0; j < SIZE; j++) 
			{
				/*
				 * Setup each of the buttons on the board
				 */
				JButton temp = new JButton();
				temp.addActionListener(this);
				buttons[i][j]=temp;
				this.boardLayout.add(temp);	   
			}
		}

		this.io = io;
		this.io.setMode(InputAndOutput.LABEL_AND_TEXT);
		this.board1 = new Board();									//create the instance of a Board object
		this.board1.setUp();
		this.io.setOutputField("Player 1: Enter your name below");
		this.items=this.board1.getItems();
		this.add(this.boardLayout, BorderLayout.CENTER);
		io.getInputField().setEnabled(true);
		this.enableBoard();	//Enable the buttons on the board
		this.print();
		this.setVisible(true); //Enable the board
	
	}
	
	
	
	
	
	/**
     * Responds to button presses on the chess board and acts accordingly
     * 
     * @param e - An event that is created when a button is pressed
     */
    public void actionPerformed(ActionEvent e)
    {

    	if(e.getSource()==restart)	//Restart
		{
			this.restart();
		}
		
		if(e.getSource()==exit)	//Exit
		{
			System.exit(0);
		}
    	
    	if(this.player1)
    	{
    		this.board1.setPlayerName(this.playerOneName, this.playerTwoName);
    	}else
    	{
    		this.board1.setPlayerName(this.playerTwoName, this.playerOneName);
    	}
    	
    	if(e.getSource()==this.queenButton && this.pawnTransformation)
    	{
             this.pawnPromotion(this.pawn.getX(), this.pawn.getY(), "Queen");
             io.getInputField().setText("");
             io.getInputField().setEnabled(false);
             this.deEnableSide();
             this.pawnTransformation = false;
    	}else if(e.getSource()==this.rookButton && this.pawnTransformation)
    	{
            this.pawnPromotion(this.pawn.getX(), this.pawn.getY(), "Rook");
            io.getInputField().setText("");
            io.getInputField().setEnabled(false);
            this.deEnableSide();
            this.pawnTransformation = false;
    	}else if(e.getSource()==this.bishopButton && this.pawnTransformation)
    	{
            this.pawnPromotion(this.pawn.getX(), this.pawn.getY(), "Bishop");
            io.getInputField().setText("");
            io.getInputField().setEnabled(false);
            this.deEnableSide();
            this.pawnTransformation = false;
    	}else if(e.getSource()==this.knightButton && this.pawnTransformation)
    	{
            this.pawnPromotion(this.pawn.getX(), this.pawn.getY(), "Knight");
            io.getInputField().setText("");
            io.getInputField().setEnabled(false);
            this.deEnableSide();
            this.pawnTransformation = false;
    	}
    	
    	/*
    	 * if the player one is not named
    	 * ask for the user to enter it and 
    	 * once it is entered move on to the player two's name
    	 */
        if(!this.playerOneNamed)
        {
            if(e.getSource()==io.getInputField())
            {
	            String s = e.getActionCommand();
	            if(!(s.equals(""))){
	            	this.playerOneName = s;
	            }
	            io.getInputField().setText("");
	            this.playerOneNamed = true;
	            this.playerTwoNamed = false;
	            this.io.setOutputField("Player 2: Enter your name below");                  
            }
        }else if(!this.playerTwoNamed)
        {
            if(e.getSource()==io.getInputField())
            {
                    String s = e.getActionCommand();
                    if(!(s.equals(playerOneName))){
                    	if(!(s.equals("")))
                    	{
                    		this.playerTwoName = s;
                    	}
                    	this.playerTwoNamed = true;
                    	this.io.setOutputField(this.playerOneName + "'s Turn");
                    	this.safeToSaveLoad = true;
                    	io.getInputField().setEnabled(false);
                        this.deEnableSide();
                        io.getInputField().setText("");
                        this.io.setMode(InputAndOutput.LABEL);
                    }else
                    {
                    	this.io.setOutputField("Player 2: Invalid name! ReEnter your name please");
                    	io.getInputField().setText("");
                    }
            }
        }else
    	{  
            if(!selected)
            {     }
            
            
            if(!this.kingCheckMove && !this.stopGame)
            {
	            //checks if the player one have any possible move if not then end the game
	            staleMate();
	            
	            //checks if the king in danger if he is check if it is a check mate
	            checkmate();
            }

                
            //checks if any of the button on the board is clicked    
            for (int i = 0; i < SIZE; i++) 
            {
                for (int j = 0; j < SIZE; j++) 
                {
                    if(!this.lostOrWon) //if there is no win or lost
                    {
                        if(e.getSource()==buttons[i][j]) //get the selected button
                        {                                
                            if(selected==false && this.isItWhitePiece(i,j)==player1 && !(this.board1.getPiece(i, j) instanceof NullPiece)) //check if the selected button is current player's side and not a nullpiece
                            {
                                selection = new Point(i,j);
                                selected = true;
                                this.colorIt(this.board1.getPiece(i, j));
                                        
                            }else if(selected)	//if a piece is selected
                            {
                            	//check if the piece can be moved the destination button
                                if(this.board1.getPiece((int)selection.getX(), (int)selection.getY()).movePossible(i, j))
                                {
                                    this.afterKingInDanger = this.board1.getPiece((int)selection.getX(), (int)selection.getY());
                                    this.afterKingInDanger2 = this.board1.getPiece(i, j);
                                    if(moveNumber<0)
                                    {
                                    	moveNumber=0;
                                    }
                                    this.saveCurrentState();
                                    this.moveNumber++;
                                    
                                    this.moveNumberRedo = 0;
                                    this.boardsredo = new ArrayList<Board>();
                                    this.playersredo = new ArrayList<Boolean>();
                                    this.kingindangersredo = new ArrayList<Boolean>();
                                    this.iosredo = new ArrayList<InputAndOutput>();
                                    this.lostOrWonsredo = new ArrayList<Boolean>();
                                    this.pawnTransformationsredo = new ArrayList<Boolean>();
                                    this.pawnsredo = new ArrayList<Piece>();
                                    
                                    this.board1.getPiece((int)selection.getX(), (int)selection.getY()).move(i, j);
                                    if(board1.getChangePlayer()){
                                    	player1 = !player1;
                                	}
                                  	selected = false;
                                    this.print();
                                    this.setVisible(true);
                                    this.clearColor();
                                    
                                    
                                    this.board1.getKing();
                        			King k = (King)this.board1.wking;
                        			if(this.board1.isInDanger(k.getX(), k.getY(), "White"))
                        			{
                        				this.io.setOutputField(this.playerOneName + " Your king is in danger");
                        			}
                        			King k2 = (King)this.board1.bking;
                        			if(this.board1.isInDanger(k2.getX(), k2.getY(), "Black"))
                        			{
                        				this.io.setOutputField(this.playerTwoName + " Your king is in danger");
                        			}
                                    if(this.afterKingInDanger.getSide().equals("White") && this.board1.whiteKingInDanger())
                                    {
                                    	kingCheckMove = true;
                                        this.io.setOutputField("Invalid Move, " + this.playerOneName + "'s your king is still in danger. Please protect it");
                                        afterKingInDanger.changePosition(afterKingInDanger.getoldX(), afterKingInDanger.getoldY());
                                        this.board1.add(afterKingInDanger);
                                        this.board1.add(afterKingInDanger2);
                                        if(board1.getChangePlayer()){
                                        	player1 = !player1;
                                    	}


                                        this.clearColor();
                                        this.print();
                                        break;
                                    }else if(this.afterKingInDanger.getSide().equals("Black") && this.board1.getkingInDanger() && !this.board1.whiteKingInDanger())
                                    {
                                    	kingCheckMove = true;
                                        this.io.setOutputField("Invalid Move, " + this.playerTwoName + "'s king is still in danger. You have to protect it");
                                        afterKingInDanger.changePosition(afterKingInDanger.getoldX(), afterKingInDanger.getoldY());
                                        this.board1.add(afterKingInDanger);
                                        this.board1.add(afterKingInDanger2);

                                        if(board1.getChangePlayer()){
                                        	player1 = !player1;
                                    	}
                                        this.clearColor();
                                        this.print();
                                        break;
                                    }else
                                    {
                                    	kingCheckMove = false;
                                        this.clearColor();
                                        this.print();
                                    }
                                        
                                }else
                                {
                                    selection =  new Point(10, 10);
                                    selected = false;
                                    this.clearColor();
                                }
                            }
                        }
                        board1.setChangePlayer(true);
                        if(this.board1.getPiece(i, j) instanceof Pawn)
                        {
                        	if(i==7||i==0)
                        	{
                        		if(player1)
                        		{
                        			io.getInputField().setEnabled(true);	//enable input and output
                            		this.io.addButtons(this.pieceButtons);
                            		this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
                        			this.io.setOutputField(this.playerTwoName + " Your pawn is promoted, Select a piece from the list below");
                        			this.io.setOutputField("<Queen or Knight or Rook or Bishop> (Default is Queen)");
                        			this.board1.clearOutputString();
                        		}else
                        		{
                        			io.getInputField().setEnabled(true);	//enable input and output
                            		this.io.addButtons(this.pieceButtons);
                            		this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
                        			this.io.setOutputField(this.playerOneName + " Your pawn is promoted, Select a piece from the list below");
                        			this.io.setOutputField("Queen or Knight or Rook or Bishop (Default is Queen)");
                        			this.board1.clearOutputString();
                        		}
                        		this.pawn = this.board1.getPiece(i, j);
                        		pawnTransformation = true;
                        		io.getInputField().setEnabled(true);
                        		this.enableBoard();
                        	}
                        }
                        //if the out put doesn't have an empty string or not a pawn transformation
                        if(!this.board1.getOutputString().equals(" ") && !pawnTransformation)
                    	{
                        	this.io.setOutputField(this.board1.getOutputString());
                    		this.board1.clearOutputString();
                    	}
                    }
                }
            }
            //tell the user which player's name
            if(!this.selected && !pawnTransformation)
            {
    	        if(player1)
    	        {
    	            this.io.setOutputField(this.playerOneName + "'s Turn");
    	        }else
    	        {
    	            this.io.setOutputField(this.playerTwoName + "'s Turn");
    	        }
            }
        }
        if(!this.kingCheckMove && !this.stopGame)
        {
	        //check if the player one have any possible move if not then end the game
	        staleMate();
	        //check if the king in danger if he is check if it is a check mate
	        checkmate();
	        this.kingCheckMove = false;
        }
        this.board1.getKing();
    }
    
    
    
    /**
     * Loads the current state of the board from a chessxml file
     * It sets the appropriate instance variables to allow the user to continue
     * the game using the saved settings
     */
    public void load()
	{
    	Board b = new Board();
    	io.getInputField().setEnabled(false);
        this.deEnableSide();
        this.io.setOutputField("You have loaded a saved game");
        
        String fileName = "temp";
		File file = new File(fileName);
		JFileChooser chooseFile = new JFileChooser();
		chooseFile.showOpenDialog(chooseFile);
		file = chooseFile.getSelectedFile();
		
		if(file!=null){
			fileName = file.getAbsolutePath();
			if(!fileName.endsWith(".chessxml"))
			{
				this.io.setOutputField("You have selected an invalid file");
				return;
			}
	    	
		}
		else{fileName = null;}
		
		if(fileName!=null)
		{
	    	try {
		            DocumentBuilderFactory documentBuilder = DocumentBuilderFactory.newInstance();
		            DocumentBuilder docBuild = documentBuilder.newDocumentBuilder();
		            Document doc = docBuild.parse (new File(fileName));
		            doc.getDocumentElement ().normalize ();
		            NodeList ListOfPiece = doc.getElementsByTagName("pieces");
		            for(int s=0; s<ListOfPiece.getLength() ; s++)
		            {
		                org.w3c.dom.Node firstQueenNode = ListOfPiece.item(s);
		                if(firstQueenNode.getNodeType() == Node.ELEMENT_NODE)
		                {
		                	org.w3c.dom.Element pieceElement = (org.w3c.dom.Element)firstQueenNode;
		                	
		                	org.w3c.dom.NodeList nameLise = pieceElement.getElementsByTagName("name");
		                    org.w3c.dom.Element nameElement = (org.w3c.dom.Element)nameLise.item(0);
		                    org.w3c.dom.NodeList nameNode = nameElement.getChildNodes();
		                    
		                    org.w3c.dom.NodeList firstMoveList = pieceElement.getElementsByTagName("firstMove");
		                    org.w3c.dom.Element firstMoveElement = (org.w3c.dom.Element)firstMoveList.item(0);
		                    org.w3c.dom.NodeList firstMoveNode = firstMoveElement.getChildNodes();
		                    
		                    org.w3c.dom.NodeList castlingPossibleList = pieceElement.getElementsByTagName("castlingPossible");
		                    org.w3c.dom.Element castlingPossibleElement = (org.w3c.dom.Element)castlingPossibleList.item(0);
		                    org.w3c.dom.NodeList castlingPossibleNode = castlingPossibleElement.getChildNodes();
		                    
		                    org.w3c.dom.NodeList xList = pieceElement.getElementsByTagName("x");
		                    org.w3c.dom.Element xElement = (org.w3c.dom.Element)xList.item(0);
		                    org.w3c.dom.NodeList xNode = xElement.getChildNodes();
	
		                    org.w3c.dom.NodeList yList = pieceElement.getElementsByTagName("y");
		                    org.w3c.dom.Element yElement = (org.w3c.dom.Element)yList.item(0);
		                    org.w3c.dom.NodeList yNode = yElement.getChildNodes();
		                    
		                    org.w3c.dom.NodeList sideList = pieceElement.getElementsByTagName("side");
		                    org.w3c.dom.Element sideElement = (org.w3c.dom.Element)sideList.item(0);
		                    org.w3c.dom.NodeList sideNode = sideElement.getChildNodes();
	
		                    org.w3c.dom.NodeList playerList = pieceElement.getElementsByTagName("player");
		                    org.w3c.dom.Element playerElement = (org.w3c.dom.Element)playerList.item(0);
		                    org.w3c.dom.NodeList playerNode = playerElement.getChildNodes();
		                    
		                    org.w3c.dom.NodeList playerOneList = pieceElement.getElementsByTagName("playerOne");
		                    org.w3c.dom.Element playerOneElement = (org.w3c.dom.Element)playerOneList.item(0);
		                    org.w3c.dom.NodeList playerOneNode = playerOneElement.getChildNodes();
		                    
		                    org.w3c.dom.NodeList playerTwoList = pieceElement.getElementsByTagName("playerTwo");
		                    org.w3c.dom.Element playerTwoElement = (org.w3c.dom.Element)playerTwoList.item(0);
		                    org.w3c.dom.NodeList playerTwoNode = playerTwoElement.getChildNodes();
		                    
		                    String nameString = ((org.w3c.dom.Node)nameNode.item(0)).getNodeValue().trim();
		                    String firstMoveString = ((org.w3c.dom.Node)firstMoveNode.item(0)).getNodeValue().trim();
		                    String castlingPossibleString = ((org.w3c.dom.Node)castlingPossibleNode.item(0)).getNodeValue().trim();
		                    String xString = ((org.w3c.dom.Node)xNode.item(0)).getNodeValue().trim();
		                    String yString = ((org.w3c.dom.Node)yNode.item(0)).getNodeValue().trim();
		                    String sideString = ((org.w3c.dom.Node)sideNode.item(0)).getNodeValue().trim();
		                    String playerString = ((org.w3c.dom.Node)playerNode.item(0)).getNodeValue().trim();
		                    String playerOneString = ((org.w3c.dom.Node)playerOneNode.item(0)).getNodeValue().trim();
		                    String playerTwoString = ((org.w3c.dom.Node)playerTwoNode.item(0)).getNodeValue().trim();
		                    
		                    
		                    int firstMoveNumber = (int)firstMoveString.charAt(0)-48;
		                    int castlingPossibleNumber = (int)castlingPossibleString.charAt(0)-48;
		                    int x = (int)xString.charAt(0)-48;
		                    int y = (int)yString.charAt(0)-48;
		                    int whichPlayer = (int)playerString.charAt(0)-48;
		                    
		                    this.playerOneName = playerOneString;
		                    this.playerTwoName = playerTwoString;
		                    Piece tempPiece = new NullPiece(x, y, this.board1);
		                    if(nameString.equals("NullPiece"))
		                    {
		                    	tempPiece = new NullPiece(x, y, this.board1);
		                    	b.add(tempPiece);
		                    }else if(nameString.equals("Bishop"))
		                    {
		                    	tempPiece = new Bishop(x, y, this.board1, sideString);
		                    	b.add(tempPiece);
		                    }else if(nameString.equals("King"))
		                    {
		                    	tempPiece = new King(x, y, this.board1, sideString);
		                    	King tempKing = (King)tempPiece;
		                    	if(firstMoveNumber==1)
		                    	{
		                    		tempKing.firstMove = true;
		                    	}else
		                    	{
		                    		tempKing.firstMove = false;
		                    	}
		                    	if(castlingPossibleNumber==1)
		                    	{
		                    		tempKing.castlingPossible = true;
		                    	}else
		                    	{
		                    		tempKing.castlingPossible = false;
		                    	}
		                    	tempPiece = (Piece)tempKing;
		                    	b.add(tempPiece);
		                    }else if(nameString.equals("Knight"))
		                    {
		                    	tempPiece = new Knight(x, y, this.board1, sideString);
		                    	b.add(tempPiece);
		                    }else if(nameString.equals("Pawn"))
		                    {
		                    	tempPiece = new Pawn(x, y, this.board1, sideString);
		                    	Pawn tempPawn = (Pawn)tempPiece;
		                    	if(firstMoveNumber==1)
		                    	{
		                    		tempPawn.firstMove = true;
		                    	}else
		                    	{
		                    		tempPawn.firstMove = false;
		                    	}
		                    	tempPiece = (Piece)tempPawn;
		                    	b.add(tempPiece);
		                    }else if(nameString.equals("Queen"))
		                    {
		                    	tempPiece = new Queen(x, y, this.board1, sideString);
		                    	b.add(tempPiece);
		                    }else if(nameString.equals("Rook"))
		                    {
		                    	tempPiece = new Rook(x, y, this.board1, sideString);
		                    	Rook tempRook = (Rook)tempPiece;
		                    	if(firstMoveNumber==1)
		                    	{
		                    		tempRook.firstMove = true;
		                    	}else
		                    	{
		                    		tempRook.firstMove = false;
		                    	}
		                    	tempPiece = (Piece)tempRook;
		                    	b.add(tempPiece);
		                    }
		                    if(whichPlayer==1)
		                    {
		                    	this.player1 = true;
		                    }else
		                    {
		                    	this.player1 = false;
		                    }
		                    this.board1 = b;
		                    this.items = this.board1.getItems();
		                    this.print();
		                }
		            }
		        }catch (SAXParseException err) { //Parse error
		        System.out.println ("** Parsing error" + ", line " + err.getLineNumber () + ", uri " + err.getSystemId ());
		        System.out.println(" " + err.getMessage ());
	
		        }catch(FileNotFoundException fnfe)
		        {
		        	JOptionPane.showMessageDialog(this, "Cannot find a saved game in this file: ", "File not found warning", JOptionPane.INFORMATION_MESSAGE, null);
		        }
		        catch (SAXException e) {
		        Exception x = e.getException ();
		        ((x == null) ? e : x).printStackTrace ();
	
		        }catch (Throwable t) {
		        t.printStackTrace ();
	        }
	        if(player1)
	        {
	            this.io.setOutputField(this.playerOneName + "'s Turn");
	        }else
	        {
	            this.io.setOutputField(this.playerTwoName + "'s Turn");
	        }
	        if(!this.kingCheckMove && !this.stopGame)
	        {
		        //check if the king in danger if he is check if it is a check mate
		        staleMate();
		        
		        //check if the king in danger if he is check if it is a check mate
		        checkmate();
	        }
		}
		this.moveNumber = 0;
		this.safeToSaveLoad = false;
		this.boards = new ArrayList<Board>();
		this.players = new ArrayList<Boolean>();
		this.kingindangers = new ArrayList<Boolean>();
		this.ios = new ArrayList<InputAndOutput>();
		this.lostOrWons = new ArrayList<Boolean>();
		this.pawnTransformations = new ArrayList<Boolean>();
		this.pawns = new ArrayList<Piece>();
		
		this.moveNumberRedo = 0;
		this.boardsredo = new ArrayList<Board>();
		this.playersredo = new ArrayList<Boolean>();
		this.kingindangersredo = new ArrayList<Boolean>();
		this.iosredo = new ArrayList<InputAndOutput>();
		this.lostOrWonsredo = new ArrayList<Boolean>();
		this.pawnTransformationsredo = new ArrayList<Boolean>();
		this.pawnsredo = new ArrayList<Piece>();
		this.io.setMode(InputAndOutput.LABEL_AND_TEXT);
		this.stopGame = false;
		this.lostOrWon = false;
		this.playerOneNamed = true;
    	this.playerTwoNamed = true;
    	this.safeToSaveLoad = true;
	}
    
    
    
    
    
    /**
     * Saves the current state of the game into a chessxml file
     * @throws IOException
     */
    public void save() throws IOException 
	{
    	if(!this.pawnTransformation)
    	{
	    	if(!stopGame)
	    	{
		    	if(this.safeToSaveLoad)
		    	{
					String s = "";
					s += "<chess>";
					for(int i=0; i<8; i++)
					{
						for(int j=0; j<8; j++)
						{
							this.items = this.board1.getItems();
							Piece currentPiece = this.items[i][j];
							s += "<pieces>";
							s += "<name>";
							s += "" + currentPiece.getClass().getSimpleName();
							s += "</name>";
							if(currentPiece instanceof King)
							{
								King king =  (King)currentPiece;
								s += "<firstMove>";
								if(king.firstMove)
								{
									s += "1";
								}else
								{
									s += "0";
								}
								s += "</firstMove>";
								s += "<castlingPossible>";
								if(king.castlingPossible)
								{
									s += "1";
								}else
								{
									s += "0";
								}
								s += "</castlingPossible>";
							}else if(currentPiece instanceof Pawn)
							{
								Pawn pawn =  (Pawn)currentPiece;
								s += "<firstMove>";
								if(pawn.firstMove)
								{
									s += "1";
								}else
								{
									s += "0";
								}
								s += "</firstMove>";
								s += "<castlingPossible>";
								s += "2";
								s += "</castlingPossible>";
							}else if(currentPiece instanceof Rook)
							{
								Rook rook =  (Rook)currentPiece;
								s += "<firstMove>";
								if(rook.firstMove)
								{
									s += "1";
								}else
								{
									s += "0";
								}
								s += "</firstMove>";
								s += "<castlingPossible>";
								s += "2";
								s += "</castlingPossible>";
							}else
							{
								s += "<firstMove>";
								s += "2";
								s += "</firstMove>";
								s += "<castlingPossible>";
								s += "2";
								s += "</castlingPossible>";
							}
							s += "<x>";
							s += "" + currentPiece.getX();
							s += "</x>";
							s += "<y>";
							s += "" + currentPiece.getY();
							s += "</y>";
							if(currentPiece.getSide().equals("White"))
							{
								s += "<side>";
								s += "White";
								s += "</side>";
							}else
							{
								s += "<side>";
								s += "Black";
								s += "</side>";
							}
							s += "<player>";
							if(this.player1)
							{
								s += "" + 1;
							}else
							{
								s += "" + 2;
							}
							s += "</player>";
							s += "<playerOne>";
							s += this.playerOneName;
							s += "</playerOne>";
							s += "<playerTwo>";
							s += this.playerTwoName;
							s += "</playerTwo>";
							s += "</pieces>";
						}
					}
					s+= "</chess>";
					this.writeToFile(s);
		    	}else
		    	{
		    		JOptionPane.showMessageDialog(this, "You cannot Save yet, Please enter your names in the Text Box below : ", "enter name first warning", JOptionPane.INFORMATION_MESSAGE, null);
		    	}
	    	}else
	    	{
	    		JOptionPane.showMessageDialog(this, "Sorry cannot save, your game is already finished.", "end game warning", JOptionPane.INFORMATION_MESSAGE, null);
	    	}
    	}else
    	{
    		JOptionPane.showMessageDialog(this, "Sorry you must finish your pawn transformation first before saving.", "pawn transfomation warning", JOptionPane.INFORMATION_MESSAGE, null);
    	}
	}
    
    
    /**
     * Writes the current state of the board into an chessxml file for save and load functions
     * @param s The string that represents the current state of the board
     * @throws IOException
     */
	public void writeToFile(String s) throws IOException 
	{
		String fileName = "temp";
		File file = new File(fileName);
		JFileChooser chooseFile = new JFileChooser();
		chooseFile.showSaveDialog(chooseFile);
		file = chooseFile.getSelectedFile();
		
		if(file!=null){
			fileName = file.getAbsolutePath()+ ".chessxml";
		}
		else{fileName = null;}
		if(fileName!=null)
		{
			FileOutputStream out = new FileOutputStream(fileName);
			try {
				 byte[] b = s.getBytes();
				 out.write(b, 0, s.length());
			} finally {
		        out.close();
			}
		}
	}
	
	
	/**
	 * Saves the current state of the board to be used in the undo and redo functions
	 */
	public void saveCurrentState()
	{
		if(this.moveNumber<0)
		{
			this.moveNumber = 0;
		}
		this.boards.add(this.moveNumber, this.board1.createBoard());
		Boolean currentplayer = new Boolean(this.player1);
		this.players.add(this.moveNumber, currentplayer);
		Boolean kingisindang = new Boolean(this.player1);
		this.kingindangers.add(this.moveNumber, kingisindang);
		InputAndOutput currentIO = this.io;
		this.ios.add(this.moveNumber, currentIO);
		Boolean lostwon = new Boolean(this.lostOrWon);
		this.lostOrWons.add(this.moveNumber, lostwon);
		Boolean pawnTranform = new Boolean(this.pawnTransformation);
		this.pawnTransformations.add(this.moveNumber, pawnTranform);
		if(this.pawn instanceof Pawn)
		{
			Pawn cp = (Pawn)this.pawn;
			Piece currentpawn = new Pawn(cp.getX(), cp.getY(), this.boards.get(this.moveNumber), cp.getSide());
			this.pawns.add(this.moveNumber, currentpawn);
		}else
		{
			Piece currentpawn = this.pawn;
			this.pawns.add(this.moveNumber, currentpawn);
		}
	}
	
	
	/**
	 * Checks if a stalemate occured
	 * If yes, it disables all the pieces on the board and prints a message
	 * on the board's output field
	 * 
	 */
	private void staleMate() {
		this.items = this.board1.getItems();
		if(this.noMoreMove("White"))
		{
			King king = (King)this.board1.wking;
			this.io.setOutputField(this.playerOneName + ", you don't have anymore moves.");
			this.io.setOutputField("You Lost");
			//this.enableBoard();
			lostOrWon = true;
			frame.setResizable(false);
			frame.setHelpIcon(HelpAndAbout.STALEMATE);
			frame.setVisible(true);
			this.io.addButtons(promptButtons);
			this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
			this.io.setVisible(true);
			this.stopGame = true;
		}else if(this.noMoreMove("Black"))
		{
			King king = (King)this.board1.bking;
			this.io.setOutputField(this.playerTwoName + " you don't have anymore moves. You Lost");
			this.io.setOutputField("You Lost");
			//this.enableBoard();
			lostOrWon = true;
			frame.setResizable(false);
			frame.setHelpIcon(HelpAndAbout.STALEMATE);
			frame.setVisible(true);
			this.io.addButtons(promptButtons);
			this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
			this.io.setVisible(true);
			this.stopGame = true;
		}
	}

	
	
	
	
	/**
	 * Checks if a checkmate occured
	 * If yes, it disables all the pieces on the board and prints a message
	 * on the board's output field
	 */
	public void checkmate() {
		if(this.board1.getkingInDanger() && player1)
		{
			Piece p = this.findCheckingPiece("White");
			King king = (King)this.board1.wking;
			ArrayList<Point> points = this.board1.pathWay(p);
			if(!this.board1.moveAnywhereOnBoard(this.board1.wking))
			{
				if(!this.checkMateDestroyer("White", points, p))
				{
					this.io.setOutputField(this.playerOneName + ", CheckMate You Lost");
					this.lostOrWon = true;
					
					frame = new HelpAndAbout();
					frame.setSize(650, 750);
					frame.getLocation(this.getLocation());
					frame.setResizable(false);
					frame.setHelpIcon(HelpAndAbout.CHECKMATE2);
					frame.setVisible(true);
					this.io.addButtons(promptButtons);
					this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
					this.io.setVisible(true);
					this.stopGame = true;
				}else
				{
					this.io.setOutputField(this.playerOneName + ", Your king is trapped; but there is a way out");
					this.kingIsInDanger = true;
				}
			}
		}else if(this.board1.getkingInDanger() && !player1)
		{
			Piece p2 = this.findCheckingPiece("Black");
			King king = (King)this.board1.bking;
			ArrayList<Point> points2 = this.board1.pathWay(p2);
			if(!this.board1.moveAnywhereOnBoard(this.board1.bking))
			{
				if(!this.checkMateDestroyer("Black", points2, p2))
				{
					//this.enableBoard();
					this.io.setOutputField(this.playerTwoName + ", CheckMate You Lost");
					this.lostOrWon = true;
					
					frame = new HelpAndAbout();
					frame.setSize(650, 750);
					frame.getLocation(this.getLocation());
					frame.setResizable(false);
					frame.setHelpIcon(HelpAndAbout.CHECKMATE1);
					frame.setVisible(true);
					this.io.addButtons(promptButtons);
					this.io.setMode(InputAndOutput.LABEL_AND_BUTTONS);
					this.io.setVisible(true);
					this.stopGame = true;
				}else
				{
					this.io.setOutputField(this.playerTwoName + ", Your king is trapped! but there is a way out");
					this.kingIsInDanger = true;
				}
			}
		}
	}
	
	
	
	
	
	/**
	 * Colors the possible moves for the selected piece on the board
	 * The selected piece is highlighted green
	 * The possible moves are highlighted yellow
	 * The possible capture moves are highlighted red
	 * 
	 * @param p - is the piece given to the method. the method check move possible of the
	 * piece will all of the block on the board and if it is true color it to yellow.
	 */
	public void colorIt(Piece p)
	{
		for (int i = 0; i < SIZE; i++) 
		{
			for (int j = 0; j < SIZE; j++) 
			{
				buttons[p.getX()][p.getY()].setBackground(Color.GREEN);
				if(p.movePossible(i, j))
				{
					if(p.isEnemy(i,j))
					{
						buttons[i][j].setBackground(Color.red);
					}else if(this.board1.getPiece(i, j) instanceof NullPiece)
					{
						buttons[i][j].setBackground(Color.YELLOW);
					}
				}
			}
		}
	}
	
	
	
	
	/**
	 * Clears the button background colors
	 */
	public void clearColor()
	{
		this.print();
	}
	
	
	
	
	
	
	/**
	 * Disable one side so player cannot select an opponents piece
	 * 
	 * @param player - is boolean set to true if it is player one turn other wise it is player two's turn
	 */
	public void enableSide(Boolean player)
	{
		if(player)
		{
			for(int i=0; i<SIZE; i++)
			{
				for(int j=0; j<SIZE; j++)
				{
					if(this.board1.getPiece(i, j).getSide().equals("Black"))
					{
						buttons[i][j].setEnabled(false);
					}
				}
			}
		}else
		{
			for(int i=0; i<SIZE; i++)
			{
				for(int j=0; j<SIZE; j++)
				{
					if(this.board1.getPiece(i, j).getSide().equals("White"))
					{
						buttons[i][j].setEnabled(false);
					}
				}
			}
		}
	}
	
	
	
	
	
	/**
	 * Enables all the board buttons so they can be clicked
	 */
	public void deEnableSide()
	{
		for(int i=0; i<SIZE; i++)
		{
			for(int j=0; j<SIZE; j++)
			{
				buttons[i][j].setEnabled(true); //Enable the button
			}
		}
	}
	
	
	/**
	 * Disables the board buttons so they cannot be clicked
	 */
	public void enableBoard()
	{
		for(int i=0; i<SIZE; i++)
		{
			for(int j=0; j<SIZE; j++)
			{
				buttons[i][j].setEnabled(false); //Disable the button
			}
		}
	}
	
	
	
	/**
	 * Checks whose turn it is
	 * 
	 * @param x X coordinate of the piece
	 * @param y Y coordinate of the piece
	 * @return
	 */
	public boolean isItWhitePiece(int x, int y)
	{
		if(this.board1.getPiece(x, y).getSide().equals("White"))
		{
			return true;
		}else if(this.board1.getPiece(x, y).getSide().equals("Black"))
		{
			return false;
		}
		return false;
	}
	
	
	
	
	
	/**
	 * Prints the board by coloring the buttons and setting the appropriate
	 * icons to the pieces on the board
	 */
	public void print()
	{
		if(!stopGame)
		{
			this.items = this.board1.getItems();
			for (int i = SIZE-1; i >= 0; i--) 
			{
				for (int j = 0; j < SIZE; j++) 
				{
					if((i+j)%2 == 0)
					{
						buttons[i][j].setBackground(new Color(117, 0, 0));
					}else
					{
						buttons[i][j].setBackground(new Color(204, 94, 47));
					}
					
					if(this.board1.getPiece(i, j) instanceof NullPiece)
					{
						buttons[i][j].setIcon(new ImageIcon("WHITENULL.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof Pawn && this.board1.getPiece(i, j).getSide().equals("White"))
					{
						buttons[i][j].setIcon(new ImageIcon("Wh-PAWN-W.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof Pawn && this.board1.getPiece(i, j).getSide().equals("Black"))
					{
						buttons[i][j].setIcon(new ImageIcon("Ba-PAWN-W.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof King && this.board1.getPiece(i, j).getSide().equals("White"))
					{
						buttons[i][j].setIcon(new ImageIcon("Wh-KING-W.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof King && this.board1.getPiece(i, j).getSide().equals("Black"))
					{
						buttons[i][j].setIcon(new ImageIcon("Ba-KING-W.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof Queen && this.board1.getPiece(i, j).getSide().equals("White"))
					{
						buttons[i][j].setIcon(new ImageIcon("Wh-QUEEN-W.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof Queen && this.board1.getPiece(i, j).getSide().equals("Black"))
					{
						buttons[i][j].setIcon(new ImageIcon("Ba-QUEEN-W.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof Bishop && this.board1.getPiece(i, j).getSide().equals("White"))
					{
						buttons[i][j].setIcon(new ImageIcon("Wh-BISHOP-W.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof Bishop && this.board1.getPiece(i, j).getSide().equals("Black"))
					{
						buttons[i][j].setIcon(new ImageIcon("Ba-BISHOP-W.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof Rook && this.board1.getPiece(i, j).getSide().equals("White"))
					{
						buttons[i][j].setIcon(new ImageIcon("Wh-ROOK-W.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof Rook && this.board1.getPiece(i, j).getSide().equals("Black"))
					{
						buttons[i][j].setIcon(new ImageIcon("Ba-ROOK-W.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof Knight && this.board1.getPiece(i, j).getSide().equals("White"))
					{
						buttons[i][j].setIcon(new ImageIcon("Wh-KNIGHT-W.PNG"));
					}else if(this.board1.getPiece(i, j) instanceof Knight && this.board1.getPiece(i, j).getSide().equals("Black"))
					{
						buttons[i][j].setIcon(new ImageIcon("Ba-KNIGHT-W.PNG"));
					}
				}
			}
		}
		this.setVisible(true);
	}

	
	
	
	
	/**
	 * This method checks if a possible checkmate can be avoided by moving a piece to block the check
	 * 
	 * 
	 * @param side - Current side of the player (White/Black)
	 * @param points - array of points which represent the pathway from the king to the piece which is checking it.
	 * @param p - The enemie's piece
	 * @return boolean value of true if the enemy piece can be blocked or killed, false if no possible block or kill
	 */
	public boolean checkMateDestroyer(String side, ArrayList<Point> points, Piece p)
	{
		int size = points.size();
		for(int x = 0; x<points.size(); x++)
		{
			for(int i=0; i<SIZE; i++)
			{
				for(int j=0; j<SIZE; j++)
				{
					Piece friendly = this.board1.getPiece(i, j);
					if(friendly.getSide().equals(side))
					{
						if(p.getType().equals(" Knight  ")||p.getType().equals("BK-Knight"))
						{
							if(friendly.movePossible(p.getX(), p.getY()))
							{
								return true;
							}
						}else if(friendly.getType().equals("   King  ")  &&  size==1 && !this.board1.isInDanger(p.getX(), p.getY(), friendly.getSide()))
						{
							return true;
						}else if(friendly.getType().equals("BK-->King")&&size==1 && !this.board1.isInDanger(p.getX(), p.getY(), p.getSide()))
						{
							return true;
						}else if(friendly.movePossible((int)points.get(x).getX(), (int)points.get(x).getY()) && !friendly.getType().equals("BK-->King") && !friendly.getType().equals("   King  "))
						{
							return true;
						}
					}
				
				}
			}
		}
		return false;
	}
	
	
	
	
	/**
	 * This method find the piece which is endangering the king
	 * 
	 * @param side - is the side of the king
	 * @return piece which is endangering the king
	 */
	public Piece findCheckingPiece(String side)
	{
		this.board1.getKing();
		Piece piece = new NullPiece(0,0,this.board1);
		for(int i=0; i<SIZE; i++)
		{
			for(int j=0; j<SIZE; j++)
			{
				piece = this.board1.getPiece(i, j);
				if(piece.getSide().equals("White")&&side.equals("Black"))
				{
					if(piece.movePossible(this.board1.bking.getX(), this.board1.bking.getY()))
					{
						return piece;
					}
				}else if(piece.getSide().equals("Black") && side.equals("White"))
				{
					if(piece.movePossible(this.board1.wking.getX(), this.board1.wking.getY()))
					{
						return piece;
					}
				}
			}
		}
		return piece;
	}
	
	
	
	
	/**
	 * This method get a piece and check if all pieces of one given side have atleast one possible move on the board.
	 * 
	 * @param side - side of the pieces which will be checked
	 * @return boolean true if a move is possible in one side, false if stalemate
	 */
	public boolean noMoreMove(String side)
	{
		for(int i=0; i<SIZE; i++)
		{
			for(int j=0; j<SIZE; j++)
			{
				Piece piece = this.board1.getPiece(i, j);
				if(piece.getSide().equals(side))
				{
					if(this.board1.moveAnywhereOnBoard(piece))
					{
						return false;
					}
				}
			}
		}
		return true;
	}
	
	
	
	
	
	/**
	 * if the piece pawn is on the far opposite block then it get to changed in to other pieces
	 * 
	 * @param p - location of the pawn
	 */
	public void pawnPromotion(int x, int y, String input2)
	{
		Piece temp = this.board1.getPiece(x, y);
		if(temp.getSide().equals("White"))
		{
			if(input2.equals("Queen")||input2.equals("QUEEN")||input2.equals("queen"))
			{
				Queen queen = new Queen(x, y, this.board1, "White");
				this.board1.add(queen);
			}else if(input2.equals("Rook")||input2.equals("ROOK")||input2.equals("rook"))
			{
				Rook rook = new Rook(x, y, this.board1, "White");
				this.board1.add(rook);
			}else if(input2.equals("Bishop")||input2.equals("BISHOP")||input2.equals("bishop"))
			{
				Bishop bishop = new Bishop(x, y, this.board1, "White");
				this.board1.add(bishop);
			}else if(input2.equals("Knight")||input2.equals("KNIGHT")||input2.equals("knight"))
			{
				Knight knight = new Knight(x, y, this.board1, "White");
				this.board1.add(knight);
			}else if(input2.equals(""))
			{
				Queen queen = new Queen(x, y, this.board1, "White");
				this.board1.add(queen);
			}else
			{
				Queen queen = new Queen(x, y, this.board1, "White");
				this.board1.add(queen);
			}
		}else
		{
			if(input2.equals("Queen")||input2.equals("QUEEN")||input2.equals("queen"))
			{
				Queen queen = new Queen(x, y, this.board1, "Black");
				this.board1.add(queen);
			}else if(input2.equals("Rook")||input2.equals("ROOK")||input2.equals("rook"))
			{
				Rook rook = new Rook(x, y, this.board1, "Black");
				this.board1.add(rook);
			}else if(input2.equals("Bishop")||input2.equals("BISHOP")||input2.equals("bishop"))
			{
				Bishop bishop = new Bishop(x, y, this.board1, "Black");
				this.board1.add(bishop);
			}else if(input2.equals("Knight")||input2.equals("KNIGHT")||input2.equals("knight"))
			{
				Knight knight = new Knight(x,y, this.board1, "Black");
				this.board1.add(knight);
			}else if(input2.equals(""))
			{
				Queen queen = new Queen(x, y, this.board1, "Black");
				this.board1.add(queen);
			}else
			{
				Queen queen = new Queen(x, y, this.board1, "Black");
				this.board1.add(queen);
			}
		}
		this.pawnTransformation = false;
		io.getInputField().setEnabled(false);
		this.board1.clearPromotion();
		
		//check if the player one have any possible move if not then end the game
        staleMate();
        
        //check if the king in danger if he is check if it is a check mate
        checkmate();
		if(player1)
        {
            this.io.setOutputField(this.playerOneName + "'s Turn");
        }else
        {
            this.io.setOutputField(this.playerTwoName + "'s Turn");
        }
		this.io.setMode(InputAndOutput.LABEL);
		this.print();
	}
	
	
	
	
	
	
	/**
	 * Restarts the board by setting all the instance variables to the original states
	 * It starts at the point where the user/player is prompted to enter the
	 * two player names
	 */
	public void restart(){
		this.moveNumber = 0;
		this.safeToSaveLoad = false;
		this.boards = new ArrayList<Board>();
		this.players = new ArrayList<Boolean>();
		this.kingindangers = new ArrayList<Boolean>();
		this.ios = new ArrayList<InputAndOutput>();
		this.lostOrWons = new ArrayList<Boolean>();
		this.pawnTransformations = new ArrayList<Boolean>();
		this.pawns = new ArrayList<Piece>();
		
		this.moveNumberRedo = 0;
		this.boardsredo = new ArrayList<Board>();
		this.playersredo = new ArrayList<Boolean>();
		this.kingindangersredo = new ArrayList<Boolean>();
		this.iosredo = new ArrayList<InputAndOutput>();
		this.lostOrWonsredo = new ArrayList<Boolean>();
		this.pawnTransformationsredo = new ArrayList<Boolean>();
		this.pawnsredo = new ArrayList<Piece>();
		
		this.io.setMode(InputAndOutput.LABEL_AND_TEXT);
		this.io.setOutputField("Welcome to Chess Game");    
		this.player1 = true;
		this.selected = false;
		this.stopGame = false;

		this.kingIsInDanger = false;
		this.lostOrWon = false;
		this.afterKingInDanger = new NullPiece(100, 100, board1);
		this.afterKingInDanger2 = new NullPiece(100, 100, board1);


		this.selection =  new Point(10, 10);
		this.playerOneName = "Player 1";
		this.playerTwoName = "Player 2";
		this.playerOneNamed = false;
		this.playerTwoNamed = true;
		this.pawnTransformation = false;
		this.pawn = new NullPiece(0, 0, this.board1);
		this.board1 = new Board();
		this.board1.setUp();
		this.items = this.board1.getItems();
		this.io.setOutputField("Player 1: Enter your name below");
		io.getInputField().setEnabled(true);
		this.enableBoard();
		this.print();
		this.setVisible(true);
		
	}

	
	/**
	 * Repeats a step that was made and was previously undo'ed.
	 */
	public void redo() {
		if(this.moveNumberRedo>0)
		{
			if(moveNumber<0)
			{
				this.moveNumber = 0;
				
			}
			this.moveNumberRedo--;
			this.board1 = this.boardsredo.get(moveNumberRedo);
			this.items = this.boardsredo.get(moveNumberRedo).getItems();
			this.player1 = this.playersredo.get(moveNumberRedo).booleanValue();
			this.kingIsInDanger = this.kingindangersredo.get(moveNumberRedo).booleanValue();
			this.io = this.iosredo.get(moveNumberRedo);
			this.lostOrWon = this.lostOrWonsredo.get(moveNumberRedo).booleanValue();
			this.pawnTransformation = this.pawnTransformationsredo.get(moveNumberRedo).booleanValue();
			this.pawn = this.pawnsredo.get(moveNumberRedo);
			
			this.moveNumber++;
			
			if(this.boards.size()==0)
			{
				this.moveNumber = 0;
			}
			this.boards.add(this.moveNumber, this.boardsredo.get(moveNumberRedo));
			this.players.add(this.moveNumber, this.playersredo.get(moveNumberRedo));
			this.kingindangers.add(this.moveNumber, this.kingindangersredo.get(moveNumberRedo));
			this.ios.add(this.moveNumber, this.iosredo.get(moveNumberRedo));
			this.lostOrWons.add(this.moveNumber, this.lostOrWonsredo.get(moveNumberRedo));
			this.pawnTransformations.add(this.moveNumber, this.pawnTransformationsredo.get(moveNumberRedo));
			this.pawns.add(this.moveNumber, this.pawnsredo.get(moveNumberRedo));
			
			this.boardsredo.remove(moveNumberRedo);
			this.playersredo.remove(moveNumberRedo);
			this.kingindangersredo.remove(moveNumberRedo);
			this.iosredo.remove(moveNumberRedo);
			this.lostOrWonsredo.remove(moveNumberRedo);
			this.pawnTransformationsredo.remove(moveNumberRedo);
			this.pawnsredo.remove(moveNumberRedo);
			if(moveNumberRedo==0)
			{
				this.boardsredo = new ArrayList<Board>();
				this.playersredo = new ArrayList<Boolean>();
				this.kingindangersredo = new ArrayList<Boolean>();
				this.iosredo = new ArrayList<InputAndOutput>();
				this.lostOrWonsredo = new ArrayList<Boolean>();
				this.pawnTransformationsredo = new ArrayList<Boolean>();
				this.pawnsredo = new ArrayList<Piece>();
			}
			this.print();
		}else
		{
			this.io.setOutputField("No more redo move possible.");
		}
		if(this.player1)
        {
            this.io.setOutputField(this.playerOneName + "'s Turn");
        }else
        {
            this.io.setOutputField(this.playerTwoName + "'s Turn");
        }
		if(this.boards.size()==0)
		{
			this.moveNumber = 0;
		}
	}

	
	/**
	 * Returns the game to the previous state. It undo's the last step and
	 * saves it as a redo step
	 */
	public void undo() 
	{		
		
		if(this.moveNumber>0)
		{
			this.saveCurrentState();
			if(this.boardsredo.size()==0)
			{
				this.moveNumberRedo = 0;
			}
			this.boardsredo.add(moveNumberRedo, this.boards.get(moveNumber));
			this.playersredo.add(moveNumberRedo, this.players.get(moveNumber));
			this.kingindangersredo.add(moveNumberRedo, this.kingindangers.get(moveNumber));
			this.iosredo.add(moveNumberRedo, this.ios.get(moveNumber));
			this.lostOrWonsredo.add(moveNumberRedo, this.lostOrWons.get(moveNumber));
			this.pawnTransformationsredo.add(moveNumberRedo, this.pawnTransformations.get(moveNumber));
			this.pawnsredo.add(moveNumberRedo, this.pawns.get(moveNumber));
			this.moveNumberRedo++;
			this.boards.remove(moveNumber);
			this.players.remove(moveNumber);
			this.kingindangers.remove(moveNumber);
			this.ios.remove(moveNumber);
			this.lostOrWons.remove(moveNumber);
			this.pawnTransformations.remove(moveNumber);
			this.pawns.remove(moveNumber);
			this.moveNumber--;
			this.board1 = this.boards.get(moveNumber);
			this.items = this.boards.get(moveNumber).getItems();
			this.player1 = this.players.get(moveNumber).booleanValue();
			this.kingIsInDanger = this.kingindangers.get(moveNumber).booleanValue();
			this.io = this.ios.get(moveNumber);
			this.lostOrWon = this.lostOrWons.get(moveNumber).booleanValue();
			this.pawnTransformation = this.pawnTransformations.get(moveNumber).booleanValue();
			this.pawn = this.pawns.get(moveNumber);
			this.print();
			if(moveNumber==0)
			{
				this.boards = new ArrayList<Board>();
				this.players = new ArrayList<Boolean>();
				this.kingindangers = new ArrayList<Boolean>();
				this.ios = new ArrayList<InputAndOutput>();
				this.lostOrWons = new ArrayList<Boolean>();
				this.pawnTransformations = new ArrayList<Boolean>();
				this.pawns = new ArrayList<Piece>();
				this.saveCurrentState();
				moveNumber = 0;
			}
		}else{ //If there  are no more undo's
			this.moveNumber = -1;
			this.io.setOutputField("No more undo move possible.");
		}
		
		
		if(this.player1){
            this.io.setOutputField(this.playerOneName + "'s Turn");
        }else{
            this.io.setOutputField(this.playerTwoName + "'s Turn");
        }
		
		
		if(this.boardsredo.size()==0)
		{
			this.moveNumberRedo = 0;
		}
		
	}
}